// pages/learn/jsbase/js_common/js_common.js
/**
 * https://www.runoob.com/w3cnote/es6-array.html
 * https://es6.ruanyifeng.com/#docs/arraybuffer
 * ArrayBuffer 字节数组缓冲区。
 *  实际字节数在创建时确定，之后只可修改其中的数据，不可修改大小。
 *  ArrayBuffer对象代表储存二进制数据的一段内存，它不能直接读写，只能通过视图（TypedArray视图和DataView视图)来读写，视图的作用是以指*  定格式解读二进制数据。
 * 视图：视图是用来操作内存的接口。（TypeArray、DataView）
 *  视图可以操作数组缓冲区或缓冲区字节的子集,并按照其中一种数值数据类型来读取和写入数据。
 *  DataView 类型是一种通用的数组缓冲区视图,其支持所有8种数值型数据类型。
 * 
 *  TypedArray视图：共包括 9 种类型的视图，比如Uint8Array（无符号 8 位整数）数组视图, Int16Array（16 位整数）数组视图, Float32Array（32 位浮点数）数组视图等等。
 *  
 *  DataView视图：可以自定义复合格式的视图，比如第一个字节是 Uint8（无符号 8 位整数）、第二、三个字节是 Int16（16 位整数）、第四个字节开始是 Float32（32 位浮点数）等等，此外还可以自定义字节序。
 */
function tsetArrayBuffer() {
  // 生成了一段 32 字节的内存区域，每个字节的值默认都是 0。可以看到，ArrayBuffer构造函数的参数是所需要的内存大小（单位字节）
  const buf0 = new ArrayBuffer(16); // 可以理解成向系统内存申请了16字节的空间，暂时没存任何东西
  // 默认方法 长度：byteLength。byteLength属性，返回所分配的内存区域的字节长度。
  console.log("arrayBuffer0 " + buf0.byteLength, buf0) // arrayBuffer 16 ArrayBuffer(16) {}
  // 默认方法 赋值(方式之一)，变量名[index] = 值
  buf0[0] = 5
  buf0[10] = 10
  console.log("arrayBuffer1 " + buf0.byteLength, buf0) // arrayBuffer1 16 ArrayBuffer(16) {0: 5, 10: 10}
  // 分割/截取数组缓冲区： slice方法，允许将内存区域的一部分，拷贝生成一个新的ArrayBuffer对象。
  // let buf0_1 = buf0.slice(1,10) // 不含 Identifier 'buf0_1' has already been declared. (22:6)【不能2个let 变量同名】
  let buf0_1 = buf0.slice(0, 10) // 不含 ,
  // slice(1,10) : arrayBuffer0_1 9 ArrayBuffer(9) {}
  console.log("arrayBuffer0_1 " + buf0_1.byteLength + ", " + buf0_1[0], buf0_1) // arrayBuffer0_1 10, undefined ArrayBuffer(10) {}
  console.log("arrayBuffer0_1 0 " + buf0.byteLength + ", " + buf0[0], buf0) // 原来的不变。arrayBuffer0_1 0 16, 5 ArrayBuffer(16) {0: 5, 10: 10}
  // for (const item of buf0) { } 报错createForOfIteratorHelper.js' is not defined。迭代器相关方法未定义
  // for (const item of buf0) {} // Invalid attempt to iterate non-iterable instance. In order to be iterable, non-array objects must have a [Symbol.iterator]() 
  // buf.push(3) //  buf.push is not a function。即常用的Array数组方法不可用。
  let a = buf0[0]
  console.log("arrayBuffer2 " + a) // arrayBuffer2 5
  // 即它不能用于复杂接口(pop、push、find、filter、for等)，只能通过视图（TypedArray视图和DataView视图)来操作
  // DataView视图的创建，需要提供ArrayBuffer对象实例作为参数。
  const dataView = new DataView(buf0) // 之前的赋值失效，重新清空了
  var da = dataView.getUint8(0) // 0
  console.log('arrayBuffer3 ' + da + ', ' + typeof (dataView), dataView)
  // dataView.push(1); // 还是不能用,push is not a function
  dataView[2] = 2;
  console.log('arrayBuffer3 dv ' + da + ', ' + dataView.getInt8(2), dataView)
  // for (const item of dataView) { } //也不能用，module '@babel/runtime/helpers/createForOfIteratorHelper.js' is not defined,

  //另一种TypedArray视图，与DataView视图的一个区别是，它不是一个构造函数，而是一组构造函数，代表不同的数据格式。
  // 向内存中申请12字节连续的内存区域，一开始默认每个字节都是0
  const buffer = new ArrayBuffer(12);

  const x0 = new Int8Array(buffer); // 
  console.log('arrayBuffer4 x0 ', x0)
  const x1 = new Int32Array(buffer); // 元素长度是3。原因32位的bit即4字节，原来空间是12字节，即从内存空间中按4字节拆分存储元素
  x1[0] = 1;
  // console.log('arrayBuffer4 x1 ' + x1.byteLength + ', length ' + x1.length, x1) //  [1, 0, 0]
  const x2 = new Uint8Array(buffer); // 8位bit的数组及1字节的数组。
  x2[0] = 2;
  console.log('arrayBuffer4 x1 ' + x1.byteLength + ', length ' + x1.length, x1)
  //arrayBuffer4 x1 12, length 3 Int32Array(3) [2, 0, 0] 说明共享[0]内存空间。12是字节空间/长度，12个字节只能存3个int

  console.log('arrayBuffer4 x2 ' + x2.byteLength + ', length ' + x2.length, x2)
  console.log('arrayBuffer4 ta x0[5] ' + x0[5] + ', x1[0] ' + x1[0] + ', x1[5] ' + x1[5] + ', x2[5] ' + x2[5], x2)
  // arrayBuffer4 ta x0[5] 0, x1[0] 2, x1[5] undefined, x2[5] 0 Uint8Array(12) [2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
  for (let i = 0; i < x2.byteLength; i++) {
    console.log(`for 410 -- ${i}  -- ${x2[i]}`)
  }
  for (let item of x2) {
    console.log('for 411 -- ', item)
  }
  // let b111 = buf0.isView() // 小程序无该方法, 使用方式不对
  console.log('for 411 --> ' + ArrayBuffer.isView(buf0), ArrayBuffer.isView(x1))
  // TypedArray视图一共包括 9 种类型，每一种视图都是一种构造函数。
  // Int8Array：8 位有符号整数，长度 1 个字节。
  // Uint8Array：8 位无符号整数，长度 1 个字节。
  // Uint8ClampedArray：8 位无符号整数，长度 1 个字节，溢出处理不同。
  // Int16Array：16 位有符号整数，长度 2 个字节。
  // Uint16Array：16 位无符号整数，长度 2 个字节。
  // Int32Array：32 位有符号整数，长度 4 个字节。
  // Uint32Array：32 位无符号整数，长度 4 个字节。
  // Float32Array：32 位浮点数，长度 4 个字节。
  // Float64Array：64 位浮点数，长度 8 个字节
  // 无符号位、有符号位8位（即1字节）的Array对比
  console.log('---------------Array对比 无 ', new Uint8Array([-10, 0, 30])) // Uint8Array(3) [246, 0, 30]
  console.log('---------------Array对比 有 ', new Int8Array([-10, 0, 30])) // Int8Array(3) [-10, 0, 30]

  // 初识构造函数
  // 创建一个8字节的ArrayBuffer
  const ab8 = new ArrayBuffer(8)
  // [[Int8Array]]: Int8Array(8)、[[Uint8Array]]: Uint8Array(8)]、[[Int16Array]]: Int16Array(4)]、[[Int32Array]]: Int32Array(2)]、[[ArrayBufferByteLength]]: 8
  console.log('--------------ab8 ', ab8)
  // 创建一个指向b的Int32视图，开始于字节0，直到缓冲区的末尾
  const i32_1 = new Int32Array(ab8);
  console.log('---------------i32_1 ', i32_1) // i32_1  Int32Array(2) [0, 0]
  // 创建一个指向b的Uint8视图，开始于字节2，直到缓冲区的末尾
  const i8a = new Int8Array(ab8, 2);
  console.log('---------------i8a ', i8a)
  const u8a = new Uint8Array(ab8, 2);
  console.log('---------------u8a ', u8a)
  // 参数一，原内存空间数组ArrayBuffer，参数二，开始的自己下标，参数三，当前类别元素长度
  const i16a = new Int16Array(ab8, 2, 2);
  console.log('---------------i16a ', i16a)

  // 字节序 指的是数值再内存中的表示方式。
  const buffer16 = new ArrayBuffer(16) // 想内存申请16字节空间
  const int32View = new Int32Array(buffer16) // 有符号(有负数)32位(4字节)数组，即此时int32View的元素长度是16/4=4
  for (let i = 0; i < int32View.length; i++) {
      int32View[i] = i * 2
  }
  console.log(` int32View ${int32View}`,int32View)
}

function testArray(twoDimArray, start, end) {
  // start含end不含
  let oneDimArray = twoDimArray.slice(start, end).flatMap(item => item.arrs);
  console.log('testArray --> ', oneDimArray);
}

Page({

  /**
   * 页面的初始数据
   */
  data: {

  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    tsetArrayBuffer();

    let twoDimArray = [
      { name: "A", arrs: [1, 2, 3] },
      { name: "B", arrs: [4, 5, 6] },
      { name: "C", arrs: [7, 8, 9] },
      { name: "D", arrs: [10, 11, 12] },
      { name: "E", arrs: [13, 14, 15] },
      { name: "G", arrs: [42, 43, 44] }
    ];
    testArray(twoDimArray,1,5);
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  }
})